Generate DTLZ2 PaletteViz

Code to generate 5D DTLZ2 PaletteViz plots for EMO-2021

This notebook generates different plots for 5D DTLZ2 for EMO-2021 paper.

In [1]:
%matplotlib notebook
%reload_ext autoreload
%autoreload 2

import sys
import os

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

plt.rcParams.update({'figure.max_open_warning': 0})
np.random.seed(123456)

Function to generate $\mathbf{R}$

In [2]:
import numpy as np
sys.path.append('../../')
from vis.generators import dtlz2
from vis.generators import c2dtlz2
from vis.generators import c0dtlz2

def generate_r(F, frontname, verbose=False):
    n = {'dtlz2': F.shape[0], 'c2dtlz2': 210000, 'c0dtlz2': 5000}
    
    LB, UB = np.mean(np.min(F, axis=0)), np.mean(np.max(F, axis=0))
    r = UB - LB
    if frontname == 'dtlz2':
        R, _ = dtlz2.surface(r=r, n=n[frontname], m=F.shape[1], mode='lhcl2')
    elif frontname == 'c2dtlz2':
        R, _, _ = c2dtlz2.surface(r=r, n=n[frontname], m=F.shape[1], mode='lhcl2')
    elif frontname == 'c0dtlz2':
        R, _, _ = c0dtlz2.surface(r=r, n=n[frontname], m=F.shape[1])
    else:
        raise ValueError("PF generation function for {:s} is not supported.".format(frontname))

    # check
    if verbose:
        print("F.shape =", F.shape)
        print("R.shape =", R.shape)
    
    return R

An L2-norm based $\mathcal{d}_{\mathbf{F}}(\cdot)$ approximation function

In [3]:
import os
import numpy as np
sys.path.append('../../')
from vis.tda import simple_shape
from vis.utils import io

def approximate_depth_l2norm(F, frontname, save_ref_depth=False, verbose=False):
    # Generate a random data points that are on the same surface as F.
    # These points are R
    R = generate_r(F, frontname, verbose=verbose)
    
    # Now find depth contours from R
    if verbose:
        print("Computing depth contours of", pf)
    Dr = simple_shape.depth_contours(R, verbose=verbose)

    # Save in a temp file
    if save_ref_depth:
        drfname = frontname + "-r-depth-cont-cvhull.csv"
        drfpath = os.path.join("/tmp", drfname)
        io.savetxt(drfpath, Dr, fmt='{:d}', delimiter=',')
    
    # Find depth contour of F from that of R
    Dr_ = Dr[::-1]
    Id = np.arange(0,F.shape[0]).astype(int)
    Df = []
    while Id.shape[0] > 0:
        # for each layer l in d_R
        for l in Dr_:
            s = []
            # for each index i in l
            for i in l.astype(int):
                # find the point j in F that is closest to R[i]
                if Id.shape[0] > 0:
                    j = np.argmin(np.linalg.norm(F[Id]-R[i], axis=1))
                    s.append(Id[j])
                    Id = np.delete(Id, j)
                else:
                    break
            if len(s) > 0:
                Df.append(np.array(s).astype(int))
    Df = np.array(Df, dtype=object)
    Df = Df[::-1]
    
    # print and check counts
    if verbose:
        print("Df.shape[0] =", Df.shape[0])
        s = 0
        for i,l in enumerate(Df):
            print("Df[{:d}].shape[0] =".format(i), l.shape[0])
            s = s + l.shape[0]
        print("total =", s)

        print("Dr.shape[0] =", Dr.shape[0])
        s = 0
        for i,l in enumerate(Dr):
            print("Dr[{:d}].shape[0] =".format(i), l.shape[0])
            s = s + l.shape[0]
        print("total =", s)

    return R,Dr,Df

Find depth-contours for the failed case

In [4]:
sys.path.append('../../')
from vis.utils import io
from vis.plotting import paletteviz


# Data where the depth contours were not 
# possible to compute, these are F's.
pf, dim = 'dtlz2-nbi', '5d'

fpath = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fpath):
    path, _ = os.path.split(fpath)
    dirs = path.split('/')
    frontname = dirs[-2].split('-')[0]

    F = np.loadtxt(fpath, delimiter=',')

    # Approximate depth contours of F from R
    R,Dr,Df = approximate_depth_l2norm(F, frontname, verbose=True, save_ref_depth=True)

    # plot and verify
    paletteviz.plot(R, ax=Axes3D(plt.figure()), depth_contours=Dr, mode='star', \
                    n_partitions=4, s=1, c='blue', verbose=True, title="PaletteViz of R")
    plt.show()

    # plot and verify
    paletteviz.plot(F, ax=Axes3D(plt.figure()), depth_contours=Df, mode='star', \
                    n_partitions=4, s=1, c='blue', verbose=True, title="PaletteViz of F")
    plt.show()

    # save the layers
    io.savetxt(os.path.join(path, "depth-cont-cvhull.csv"), Df, fmt='{:d}', delimiter=',')
F.shape = (999, 5)
R.shape = (999, 5)
Computing depth contours of dtlz2-nbi
Projecting on a simplex and collapsing.
Computing depth contour 0 ...
Computing depth contour 1 ...
Computing depth contour 2 ...
Computing depth contour 3 ...
Computing depth contour 4 ...
Computing depth contour 5 ...
Computing depth contour 6 ...
Computing depth contour 7 ...
Df.shape[0] = 9
Df[0].shape[0] = 224
Df[1].shape[0] = 209
Df[2].shape[0] = 169
Df[3].shape[0] = 145
Df[4].shape[0] = 99
Df[5].shape[0] = 69
Df[6].shape[0] = 59
Df[7].shape[0] = 21
Df[8].shape[0] = 4
total = 999
Dr.shape[0] = 9
Dr[0].shape[0] = 224
Dr[1].shape[0] = 209
Dr[2].shape[0] = 169
Dr[3].shape[0] = 145
Dr[4].shape[0] = 99
Dr[5].shape[0] = 69
Dr[6].shape[0] = 59
Dr[7].shape[0] = 21
Dr[8].shape[0] = 4
total = 999
Plotting palette-star-viz.
Using depth contours ndarray.
Plotting palette-star-viz.
Using depth contours ndarray.

Compute trade-offs

In [5]:
%matplotlib notebook

sys.path.append('../../')
from vis.utils import dm
from vis.plotting.utils import resize_by_tradeoff, default_color, \
                                color_by_cv, enhance_color

eps = dm.epsilons

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    Mu,Ik = dm.tradeoff(F, epsilon=eps[dim], penalize_extremes=False)
    mupathf = os.path.join(path, "mu.csv")
    np.savetxt(mupathf, Mu, delimiter=',', fmt="%1.4e")
    muidxpathf = os.path.join(path, "muid.csv")
    np.savetxt(muidxpathf, Ik, delimiter=',', fmt="%d")

    # default color array
    C = default_color(F.shape[0], alpha=0.5)

    # change the size w.r.t. Mu, the values are 
    # too big for smaller size plots, so we make 
    # them half.
    S = resize_by_tradeoff(Mu, k=Ik)

    # load CV if exists, use it for coloring
    cvpathf = os.path.join(path, "datacv.csv")
    if os.path.exists(cvpathf):
        CV = np.loadtxt(cvpathf, delimiter=',')
        C = color_by_cv(CV)

    # enhance the knees with red
    C = enhance_color(C, k=Ik)

    # plot
    ax = Axes3D(plt.figure())
    ax.scatter(F[:,0], F[:,1], F[:,2], c=C, s=S)
    
    plt.show()
else:
    print("Error: {:s} not found.".format(fullpathf))
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi

Get appropriate color codings and other markings

In [6]:
sys.path.append('../../')
from vis.plotting.utils import resize_by_tradeoff, color_by_dist, color_by_cv, enhance_color

def load_props(path):
    r"""
    Load CV, Mu, Ik and S from path.
    """
    CV = None
    cvpathf = os.path.join(path, "datacv.csv")
    if os.path.exists(cvpathf):
        CV = np.loadtxt(cvpathf)

    # load the Mu values
    Mu = None
    mupathf = os.path.join(path, "mu.csv")
    if os.path.exists(mupathf):
        Mu = np.loadtxt(mupathf)

    # load the knee indices
    Ik = None
    kpathf = os.path.join(path, "muid.csv")
    if os.path.exists(kpathf):
        Ik = np.loadtxt(kpathf, dtype = int)
        
    return CV, Mu, Ik

def decide_size_color(CV, Mu, Ik):
    r"""
    Decide point-size and color from `CV`, `Mu` and `Ik`
    """
    # decide point-size
    S = 1
    if Mu is not None and Ik is not None:
        S = resize_by_tradeoff(Mu, k=Ik)

    # decide colors
    # C = default_color(F.shape[0], alpha=0.5)
    M = np.mean(F, axis=0)
    C, _ = color_by_dist(F, M)
    
    # if CV is available, use CV to color
    if CV is not None:
        C = color_by_cv(CV)

    # enhance knee points
    if Ik is not None:
        C = enhance_color(C, Ik)
    return S, C

Now do a scatter plot with appropriate colorcodings and markings

In [7]:
%matplotlib notebook
sys.path.append('../../')
from vis.plotting import scatter
from vis.plotting.scatter import camera_angles

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)

    pdffigpath = os.path.join(path, "scatter3d.pdf")
    svgfigpath = os.path.join(path, "scatter3d.svg")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        scatter.plot(F, ax=Axes3D(plt.figure()), s=S, c=C, euler=(45,25))#camera_angles[pf][dim])
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', pad_inches=0, dpi=150)
        plt.savefig(svgfigpath, bbox_inches='tight', pad_inches=0, dpi=150, format='svg')
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi

Do paletteviz original

In [8]:
%matplotlib notebook
sys.path.append('../../')
from vis.plotting import paletteviz
from vis.plotting.paletteviz import camera_angles_star

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)

    pdffigpath = os.path.join(path, "palette-starviz.pdf")
    svgfigpath = os.path.join(path, "palette-starviz.svg")
    depth_contour_path = os.path.join(path, "depth-cont-cvhull.csv")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        paletteviz.plot(F, ax=Axes3D(plt.figure()), depth_contours=depth_contour_path, mode='star', \
                        n_partitions=4, s=S, c=C, verbose=True, euler=(-40,15)) #camera_angles_star[pf][dim])
        
        # try to remove white space as much as possible
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        plt.gca().xaxis.set_major_locator(plt.NullLocator())
        plt.gca().yaxis.set_major_locator(plt.NullLocator())
        plt.gca().zaxis.set_major_locator(plt.NullLocator())
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', dpi=150, pad_inches=0)
        plt.savefig(svgfigpath, bbox_inches='tight', dpi=150, pad_inches=0, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
Plotting palette-star-viz.
Loading depth contours from ../../data/dtlz2-nbi/5d/depth-cont-cvhull.csv.

Fig1: Plot 1000 points using PaletteViz in four levels.

Show point $f^{(0)}$ on the plot with a bright color (say, red or something, which is not in the paletteviz). This one should plotted in way so that all points are nicely visible.

In [9]:
%matplotlib notebook
import matplotlib.colors as mc
sys.path.append('../../')
from vis.plotting import scatter
from vis.plotting.scatter import camera_angles
from vis.plotting.utils import default_color, enhance_color

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)
    
    # change the color and size according to the requirements
    C = default_color(F.shape[0], c=mc.TABLEAU_COLORS['tab:gray'], alpha=0.5)
    if0 = np.array([0])
    C = enhance_color(C, if0)
    S[if0] = S[if0] * 6.0

    pdffigpath = os.path.join(path, "scatter3d-fig1.pdf")
    svgfigpath = os.path.join(path, "scatter3d-fig1.svg")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        # plot
        ax = Axes3D(plt.figure()) 
        scatter.plot(F, ax=ax, s=S, c=C, euler=(45,25)) #camera_angles[pf][dim])
        # mark point
        ax.text(F[if0,0][0], F[if0,1][0], z=F[if0,2][0], s=r'$\mathbf{f^{{(0)}}}$', \
                ha='right', va='bottom', fontsize='large')

        # remove white space
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', pad_inches=0, dpi=150)
        plt.savefig(svgfigpath, bbox_inches='tight', pad_inches=0, dpi=150, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
In [10]:
%matplotlib notebook
import matplotlib.colors as mc
sys.path.append('../../')
from vis.plotting import paletteviz
from vis.plotting.paletteviz import camera_angles_star
from vis.plotting.utils import default_color, enhance_color

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)
    
    # change the color and size according to the requirements
    C = default_color(F.shape[0], c=mc.TABLEAU_COLORS['tab:gray'], alpha=0.5)
    if0 = np.array([0])
    C = enhance_color(C, if0)
    S[if0] = S[if0] * 6.0

    pdffigpath = os.path.join(path, "palette-starviz-fig1.pdf")
    svgfigpath = os.path.join(path, "palette-starviz-fig1.svg")
    depth_contour_path = os.path.join(path, "depth-cont-cvhull.csv")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        # plot
        ax = Axes3D(plt.figure()) 
        _,P = paletteviz.plot(F, ax=ax, depth_contours=depth_contour_path, mode='star', \
                        n_partitions=4, s=S, c=C, verbose=True, euler=(-40,15)) # camera_angles_star[pf][dim])
        # mark points
        ax.text(P[if0,0][0], P[if0,1][0], z=P[if0,2][0], s=r'$\mathbf{f^{{(0)}}}$', \
                ha='right', va='bottom', fontsize='large')
        
        # try to remove white space as much as possible
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        plt.gca().xaxis.set_major_locator(plt.NullLocator())
        plt.gca().yaxis.set_major_locator(plt.NullLocator())
        plt.gca().zaxis.set_major_locator(plt.NullLocator())
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', dpi=150, pad_inches=0)
        plt.savefig(svgfigpath, bbox_inches='tight', dpi=150, pad_inches=0, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
Plotting palette-star-viz.
Loading depth contours from ../../data/dtlz2-nbi/5d/depth-cont-cvhull.csv.

Fig 2: On the another PaletteViz with same 1000 points, plot $f^{(1)}$ and join with an arrow from $f^{(0)}$.

Mark three equidistant intermediate points on the line:

  • $p_1 = f^{(0)} + 0.25 (f^{(1)} - f^{(0)})$
  • $p_2 = f^{(0)} + 0.50 (f^{(1)} - f^{(0)})$
  • $p_3 = f^{(0)} + 0.75 (f^{(1)} - f^{(0)})$

Then, mark $z^{(1)}$ to $z^{(3)}$ points with another bright color. Join $z^{(1)}$ with the first intermediate point, and so on, to indicate that $z^{(1)}$ is obtained from p1 and so on. These points may be at different levels (if not, let me know, I need to add more points). Here, focus on near all these points.

In [11]:
from scipy.spatial import cKDTree

# two starting point indices
print(F.shape)
if0f1 = np.array([0, 300])
f0 = F[if0f1[0],:]
f1 = F[if0f1[1],:]

# three intermediate points
p1 = f0 + 0.25 * (f1 - f0)
p2 = f0 + 0.50 * (f1 - f0)
p3 = f0 + 0.75 * (f1 - f0)

# build a tree
tree = cKDTree(F)

# get the intermediate point indices
_,ip1 = tree.query(p1, k=1)
_,ip2 = tree.query(p2, k=1)
_,ip3 = tree.query(p3, k=1)

if0f1 = np.array([if0f1[0], ip1, ip2, ip3, if0f1[1]])
print(if0f1)
(999, 5)
[  0 517 376 600 300]
In [12]:
%matplotlib notebook
sys.path.append('../../')
from vis.plotting import scatter
from vis.plotting.scatter import camera_angles
from vis.plotting.utils import default_color, enhance_color, Arrow3D

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)
    
    # change the color and size according to the requirements
    C = default_color(F.shape[0], c=mc.TABLEAU_COLORS['tab:gray'], alpha=0.5)
    # enhance intermediate points
    C = enhance_color(C, if0f1, alpha=1.0)
    S[if0f1] = S[if0f1] * 6.0
    # point labels
    labels = [r'$\mathbf{f^{{(0)}}}$', r'$\mathbf{p_{{1}}}$', r'$\mathbf{p_{{2}}}$', \
              r'$\mathbf{p_{{3}}}$', r'$\mathbf{f^{{(1)}}}$']

    pdffigpath = os.path.join(path, "scatter3d-fig2.pdf")
    svgfigpath = os.path.join(path, "scatter3d-fig2.svg")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        # plot
        ax = Axes3D(plt.figure())
        scatter.plot(F, ax=ax, s=S, c=C, euler=(45,25))#camera_angles[pf][dim])

        # mark points
        for i in range(if0f1.shape[0]):
            ax.text(F[if0f1[i],0]-0.025, F[if0f1[i],1]-0.025, z=F[if0f1[i],2], s=labels[i], \
                    ha='left', va='bottom', fontsize='large')
        
        # draw arrows
        for i in range(if0f1.shape[0]-1):
            a = Arrow3D(\
                    [F[if0f1[i],0], F[if0f1[i+1],0]], \
                    [F[if0f1[i],1], F[if0f1[i+1],1]], \
                    [F[if0f1[i],2], F[if0f1[i+1],2]], \
                    mutation_scale = 10, lw = 0.75, \
                    arrowstyle = "-|>", color = 'black')
            ax.add_artist(a)

        # remove white spaces
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', pad_inches=0, dpi=150)
        plt.savefig(svgfigpath, bbox_inches='tight', pad_inches=0, dpi=150, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
In [13]:
%matplotlib notebook
import matplotlib.colors as mc
sys.path.append('../../')
from vis.plotting import paletteviz
from vis.plotting.paletteviz import camera_angles_star
from vis.plotting.utils import default_color, enhance_color

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)
    
    # change the color and size according to the requirements
    C = default_color(F.shape[0], c=mc.TABLEAU_COLORS['tab:gray'], alpha=0.5)
    # enhance intermediate points
    C = enhance_color(C, if0f1, alpha=1.0)
    S[if0f1] = S[if0f1] * 6.0
    # point labels
    labels = [r'$\mathbf{f^{{(0)}}}$', r'$\mathbf{p_{{1}}}$', r'$\mathbf{p_{{2}}}$', \
              r'$\mathbf{p_{{3}}}$', r'$\mathbf{f^{{(1)}}}$']
    # label pos
    lpos = [['left', 'bottom'], ['left', 'bottom'], ['left', 'bottom'], ['right', 'bottom'], ['left', 'bottom']]

    pdffigpath = os.path.join(path, "palette-starviz-fig2.pdf")
    svgfigpath = os.path.join(path, "palette-starviz-fig2.svg")
    depth_contour_path = os.path.join(path, "depth-cont-cvhull.csv")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        ax = Axes3D(plt.figure())
        _,P = paletteviz.plot(F, ax=ax, depth_contours=depth_contour_path, mode='star', \
                        n_partitions=4, s=S, c=C, verbose=True, euler=(-40,15)) # camera_angles_star[pf][dim])
        
        # mark points
        for i in range(if0f1.shape[0]):
            ax.text(P[if0f1[i],0]+0.025, P[if0f1[i],1]+0.025, z=P[if0f1[i],2], s=labels[i], \
                    ha=lpos[i][0], va=lpos[i][1], fontsize='large')
        
        # draw arrows
        for i in range(len(if0f1)-1):
            a = Arrow3D(\
                    [P[if0f1[i],0], P[if0f1[i+1],0]], \
                    [P[if0f1[i],1], P[if0f1[i+1],1]], \
                    [P[if0f1[i],2], P[if0f1[i+1],2]], \
                    mutation_scale = 10, lw = 0.75, \
                    arrowstyle = "-|>", color = 'black')
            ax.add_artist(a)
        
        # try to remove white space as much as possible
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        plt.gca().xaxis.set_major_locator(plt.NullLocator())
        plt.gca().yaxis.set_major_locator(plt.NullLocator())
        plt.gca().zaxis.set_major_locator(plt.NullLocator())
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', dpi=150, pad_inches=0)
        plt.savefig(svgfigpath, bbox_inches='tight', dpi=150, pad_inches=0, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
Plotting palette-star-viz.
Loading depth contours from ../../data/dtlz2-nbi/5d/depth-cont-cvhull.csv.

Fig 3: On the another PaletteViz with same 1000 points, plot f^(2) and join with an arrow from f^(1).

Then, mark intermediate points

  • $p_1 = f^{(1)} + 0.3333 (f^{(2)} - f^{(1)})$
  • $p_2 = f^{(1)} + 0.6667 (f^{(2)} - f^{(1)})$
  • $p_2 = f^{(1)} + 0.9999 (f^{(2)} - f^{(1)})$

and $z^{(1)}$ to $z^{(2)}$ points with another bright color. Join them. Then, plot the third iteration points $f^{(3)}$, join with $f^{(2)}$, and then mark two intermediate points $p_1$ and $p_2$ and their respective points $z^{(1)}$ and $z^{(2)}$ and join. Here also focus on the points.

In [14]:
from scipy.spatial import cKDTree

# two starting point indices
print(F.shape)
if0f1 = np.array([0, 300])
f0 = F[if0f1[0],:]
f1 = F[if0f1[1],:]

# three intermediate points
p1 = f0 + 0.3333 * (f1 - f0)
p2 = f0 + 0.6667 * (f1 - f0)

# build a tree
tree = cKDTree(F)

# get the intermediate point indices
_,ip1 = tree.query(p1, k=1)
_,ip2 = tree.query(p2, k=1)

if0f1 = np.array([if0f1[0], ip1, ip2, if0f1[1]])
print(if0f1)
(999, 5)
[  0 293 376 300]
In [15]:
%matplotlib notebook
sys.path.append('../../')
from vis.plotting import scatter
from vis.plotting.scatter import camera_angles
from vis.plotting.utils import default_color, enhance_color, Arrow3D

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)
    
    # change the color and size according to the requirements
    C = default_color(F.shape[0], c=mc.TABLEAU_COLORS['tab:gray'], alpha=0.5)
    # enhance intermediate points
    C = enhance_color(C, if0f1, alpha=1.0)
    S[if0f1] = S[if0f1] * 6.0
    # point labels
    labels = [r'$\mathbf{f^{{(0)}}}$', r'$\mathbf{p_{{1}}}$', r'$\mathbf{p_{{2}}}$', r'$\mathbf{f^{{(1)}}}$']

    pdffigpath = os.path.join(path, "scatter3d-fig3.pdf")
    svgfigpath = os.path.join(path, "scatter3d-fig3.svg")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        # plot
        ax = Axes3D(plt.figure())
        scatter.plot(F, ax=ax, s=S, c=C, euler=(45,25))#camera_angles[pf][dim])
        
        # mark points
        for i in range(if0f1.shape[0]):
            ax.text(F[if0f1[i],0]-0.025, F[if0f1[i],1]-0.025, z=F[if0f1[i],2], s=labels[i], \
                    ha='left', va='bottom', fontsize='large')
        
        # draw arrows
        for i in range(if0f1.shape[0]-1):
            a = Arrow3D(\
                    [F[if0f1[i],0], F[if0f1[i+1],0]], \
                    [F[if0f1[i],1], F[if0f1[i+1],1]], \
                    [F[if0f1[i],2], F[if0f1[i+1],2]], \
                    mutation_scale = 10, lw = 0.75, \
                    arrowstyle = "-|>", color = 'black')
            ax.add_artist(a)
            
        # remove white space
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', pad_inches=0, dpi=150)
        plt.savefig(svgfigpath, bbox_inches='tight', pad_inches=0, dpi=150, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
In [16]:
%matplotlib notebook
import matplotlib.colors as mc
sys.path.append('../../')
from vis.plotting import paletteviz
from vis.plotting.paletteviz import camera_angles_star
from vis.plotting.utils import default_color, enhance_color

pf,dim = 'dtlz2-nbi', '5d'

fullpathf = "../../data/{0:s}/{1:s}/dataf.csv".format(pf, dim)
if os.path.exists(fullpathf):
    path, filenamef = os.path.split(fullpathf)
    dirs = path.split('/')
    frontname = dirs[-2]

    # load the front
    F = np.loadtxt(fullpathf, delimiter=',')
    print(fullpathf, F.shape, dirs, frontname)

    CV, Mu, Ik = load_props(path)
    S,C = decide_size_color(CV, Mu, Ik)
    
    # change the color and size according to the requirements
    C = default_color(F.shape[0], c=mc.TABLEAU_COLORS['tab:gray'], alpha=0.5)
    # enhance intermediate points
    C = enhance_color(C, if0f1, alpha=1.0)
    S[if0f1] = S[if0f1] * 6.0
    # point labels
    labels = [r'$\mathbf{f^{{(0)}}}$', r'$\mathbf{p_{{1}}}$', r'$\mathbf{p_{{2}}}$', r'$\mathbf{f^{{(1)}}}$']
    # label pos
    lpos = [['left', 'bottom'], ['right', 'bottom'], ['right', 'bottom'], ['left', 'bottom']]

    pdffigpath = os.path.join(path, "palette-starviz-fig3.pdf")
    svgfigpath = os.path.join(path, "palette-starviz-fig3.svg")
    depth_contour_path = os.path.join(path, "depth-cont-cvhull.csv")
    with plt.rc_context({"text.usetex": True, "font.size": 12}):
        # plot
        ax = Axes3D(plt.figure())
        _,P = paletteviz.plot(F, ax=ax, depth_contours=depth_contour_path, mode='star', \
                        n_partitions=4, s=S, c=C, verbose=True, euler=(-40,15)) # camera_angles_star[pf][dim])
        
        # mark points
        for i in range(if0f1.shape[0]):
            ax.text(P[if0f1[i],0]-0.025, P[if0f1[i],1]-0.025, z=P[if0f1[i],2], s=labels[i], \
                    ha=lpos[i][0], va=lpos[i][1], fontsize='large')
        
        # draw arrows
        for i in range(if0f1.shape[0]-1):
            a = Arrow3D(\
                    [P[if0f1[i],0], P[if0f1[i+1],0]], \
                    [P[if0f1[i],1], P[if0f1[i+1],1]], \
                    [P[if0f1[i],2], P[if0f1[i+1],2]], \
                    mutation_scale = 10, lw = 0.75, \
                    arrowstyle = "-|>", color = 'black')
            ax.add_artist(a)
        
        # try to remove white space as much as possible
        plt.subplots_adjust(top=0.01, bottom=0, right=0.01, left=0, hspace=0, wspace=0)
        plt.margins(0,0,0)
        plt.gca().xaxis.set_major_locator(plt.NullLocator())
        plt.gca().yaxis.set_major_locator(plt.NullLocator())
        plt.gca().zaxis.set_major_locator(plt.NullLocator())
        
        # save the fig
        plt.savefig(pdffigpath, bbox_inches='tight', dpi=150, pad_inches=0)
        plt.savefig(svgfigpath, bbox_inches='tight', dpi=150, pad_inches=0, format='svg')
        
        # show
        plt.show()
../../data/dtlz2-nbi/5d/dataf.csv (999, 5) ['..', '..', 'data', 'dtlz2-nbi', '5d'] dtlz2-nbi
Plotting palette-star-viz.
Loading depth contours from ../../data/dtlz2-nbi/5d/depth-cont-cvhull.csv.
In [ ]: